--[[
    NuckPluck - An android game for learning the Thai alphabet
    Copyright (C) 2013 Nathan Kieffer

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

    Contact: nathankieffer@gmail.com
--]]

local storyboard = require("storyboard")
local map = require("map")
local controller = require("controller")
local player = require("player")
local enemy = require("enemy")
local cloud = require("cloud")
local widget = require("widget")
local physics = require("physics")
local scene = storyboard.newScene()

--I'm using physics only for collisions so I turn off the gravity.
physics.setGravity(0,0)
physics.start()

--this table will hold additional enemy generator functions
local generators = {
   ["green"] = enemy.newEnemy
}

function scene:createScene(event)
   print(event.name)
   local group = self.view
   self.livesStatus = display.newText(group, "", 0,0, native.systemFont, 48)
   self.livesStatus.anchorX = 0
   self.livesStatus.anchorY = 0
end

function scene:enterScene(event)
   local group = self.view

   --add some clouds to the background
   self.clouds = {}
   for i=1,5 do
      self.clouds[#self.clouds + 1] = cloud.newCloud(group, i % 2 + 1)
   end

   --get the level data passed in from the level menu
   self.mapData = event.params
   self.levelCompleted = false
  
   --create the map
   self.map = map.newMap(self.mapData, 10,10, 50)
   group:insert(self.map)

   --create the controller
   self.controller = controller.newController(self.map)
   self.controller:setPosition(display.contentWidth * 0.5,			       display.contentHeight - 100)--self.controller.height * 0.5)
   group:insert(self.controller)

   --create the player
   self.player = player.newPlayer()
   --this is so I can access player fields inside the map table functions
   self.map.player = self.player
   self.map:insert(self.player)

   --populate the map
   self.map:generate()

   self.player:toFront()

   --create the enemies table for use in the enterFrame function
   self.enemies = {["green"] = {}}
   Runtime:addEventListener("enterFrame", scene)

end

function scene:exitScene(event)
   
   --clear the map, controller, and player
   if self.map then
      self.view:remove(self.map)
      self.map = nil
   end
   if self.controller then
      self.controller:removeSelf()
      self.controller = nil
   end
   if self.player then
      Runtime:removeEventListener("enterFrame", self.player)
      self.player:removeSelf()
      self.player = nil
   end

   --get rid of all of the enemies
   if self.enemies then
   for i,enemySet in pairs(self.enemies) do
      for i=1,#enemySet do
	 local enemy = enemySet[i]
	 Runtime:removeEventListener("enterFrame", enemy)
	 enemy:removeSelf()
	 enemy = nil
      end
   end
   end
   if self.clouds then
   --get rid of the clouds
   for i,cloud in pairs(self.clouds) do
      cloud:removeSelf()
   end
   end
end

function scene:enterFrame(event)

   --update the lives counter
   self.livesStatus.text = self.player.lives
   self.livesStatus:toFront()
   
   --If player has beaten the level, go back to the level menu
   if self.levelCompleted then
      Runtime:removeEventListener("enterFrame", scene)
      storyboard.gotoScene("menu")
      return
   end

   --check to see if the player has matched all of the letters and goals
   --set levelCompleted variable to true
   if self.mapData and self.map.correct >= #self.mapData.data then
      self.levelCompleted = true
      return

   end
   
   --alias some fields for repeated access of fields
   local c = self.controller
   local m = self.map
   local p = self.player
   
   --check to see if player has collided with a monster or an air tile
   if p.isFalling then
      --reset player position
      p.isFalling = false
      self.map:center(true)
   end

   --move player and map using controllor movex, movey and step
   c:slowDown()
   m:move(c.movex * c.step, c.movey * c.step)
   p:move(-c.movex * c.step, -c.movey * c.step, c.angle)

   --move enemies
   for i,enemySet in pairs(self.enemies) do
      for i=1,#enemySet do
	 enemySet[i]:track(p)
      end
   end

   --add more enemies
   for i,enemyType in pairs(self.mapData.enemies) do
      if math.random() >= enemyType.prob and #self.enemies[enemyType.type] < enemyType.max then
	 local isHead = true
	 print("A:", enemyType.speed)
	 local e = generators[enemyType.type](isHead, enemyType.speed)

	 self.map:insert(e)
	 print(enemyType.start.x, enemyType.start.y)
	 local start = enemyType.start[math.random(#enemyType.start)]
	 e:setStartPosition(start)
	 print(e.x, e.y)
	 self.enemies[enemyType.type][#self.enemies[enemyType.type] + 1] = e 
      end
   end
   
   --This section prevents the player running into the wall from moving the sprite off of its centered location
   --should be a map methof
   local px, py = p:localToContent(0,0)
   px = math.round(px)
   py = math.round(py)
   if math.round(px) ~= 160 or math.round(py) ~= 144 then
      transition.to(self.map,{x = self.map.x -  (px - 160),
		    y = self.map.y -  (py - 144)})
   end
end

scene:addEventListener("createScene", scene)
scene:addEventListener("enterScene", scene)
scene:addEventListener("exitScene", scene)
return scene